package com.qingzhuge.resource.service.impl;


import com.google.common.collect.Lists;
import com.qingzhuge.common.enums.EResourceType;
import com.qingzhuge.resource.dao.SysResourceDao;
import com.qingzhuge.resource.vo.TreeVo;
import com.qingzhuge.resource.entity.SysResource;
import com.qingzhuge.resource.service.ISysResourceService;
import com.qingzhuge.service.BasePkLongServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @author : zero.xiao
 * @description :
 * @date :2018/6/12 0012 下午 17:22
 * @modified :
 * @since : 1.0.0
 */
@Slf4j
@Service
@CacheConfig(cacheNames = SysResourceServiceImpl.CACHE_NAME)
public class SysResourceServiceImpl extends BasePkLongServiceImpl<SysResourceDao, SysResource> implements ISysResourceService {
    final static String CACHE_NAME = "sysResourceService";

    @Override
    @Cacheable(key = "#parent.id.toString()", condition = "#parent != null")
    public List<SysResource> queryListByParent(SysResource parent, List<Long> resourceIdList) {
        List<SysResource> resources = queryListByParent(parent);
        if (resourceIdList == null) {
            return resources;
        }

        List<SysResource> resourceList = new ArrayList<>();
        for (SysResource resource : resources) {
            if (resourceIdList.contains(resource.getId())) {
                resourceList.add(resource);
            }
        }
        return resourceList;
    }

    @Override
    @Cacheable(key = "#parent.id.toString()", condition = "#parent != null && #parent.id != null")
    public List<SysResource> queryListByParent(SysResource parent) {
        List<SysResource> resources;
        if (null == parent || parent.getId() < 1) {
            resources = baseDao.queryByParentIsNullOrderByOrderNumAsc();
        } else {
            resources = baseDao.queryByParentOrderByOrderNumAsc(parent);
        }
        getChildResource(resources);
        return resources;
    }

    private void getChildResource(List<SysResource> resources) {
        resources.forEach(resource -> {
            if (!resource.getType().equals(EResourceType.button)) {
                List<SysResource> resourceList = queryListByParent(resource);
                if (resource.getParent() == null || resource.getParent().getId() == 0) {
                    resource.setLeaf(0);
                }
                getChildResource(resourceList);
                resource.setChildren(resourceList);
            }
        });
    }

    @Override
    @Cacheable(key = "'tree：'.concat(#parent.id)", condition = "#parent != null && #parent.id != null")
    public List<TreeVo> queryTreeListByParent(SysResource parent) {
        List<SysResource> resources;
        if (null == parent || parent.getId() < 1) {
            resources = baseDao.queryByParentIsNullOrderByOrderNumAsc();
        } else {
            resources = baseDao.queryByParentOrderByOrderNumAsc(parent);
        }
        List<TreeVo> trees = Lists.newArrayList();
        getChildTree(resources, trees);
        return trees;
    }

    private void getChildTree(List<SysResource> resources, List<TreeVo> trees) {
        resources.forEach(resource -> {
            if (resource.getType().equals(EResourceType.menu) ||
                    resource.getType().equals(EResourceType.catalog) ||
                    resource.getType().equals(EResourceType.button)) {
                TreeVo tree = new TreeVo();
                tree.setId(resource.getId());
                tree.setName(resource.getName());
                tree.setLabel(resource.getName());
                tree.setType(resource.getType());
                //设置叶子
                List<SysResource> resourceList = queryListByParent(resource);
                List<TreeVo> ts = Lists.newArrayList();
                getChildTree(resourceList, ts);
                tree.setChildren(ts);
                trees.add(tree);
            }
        });
    }


    @Override
    @Cacheable(key = "#root.methodName")
    public List<SysResource> queryNotButtonList() {
        return baseDao.queryByTypeButtonNot(EResourceType.button);
    }

    /**
     * 获取所有菜单列表
     */
    @Override
    @Cacheable
    public List<SysResource> queryAllResourceList(List<Long> resourceIdList) {
        //查询根菜单列表
        List<SysResource> resourceList = queryListByParent(null, resourceIdList);
        //递归获取子菜单
        getResourceTreeList(resourceList, resourceIdList);
        return resourceList;
    }

    /**
     * 递归
     */
    private List<SysResource> getResourceTreeList(List<SysResource> resourceList, List<Long> resourceIdList) {
        List<SysResource> resources = new ArrayList<>();

        for (SysResource entity : resourceList) {
            //目录
            if (entity.getType().equals(EResourceType.catalog)) {
                entity.setList(getResourceTreeList(queryListByParent(entity, resourceIdList), resourceIdList));
            }
            resources.add(entity);
        }

        return resources;
    }

    @Override
    @Cacheable(cacheNames = CACHE_NAME, condition = "#uid!=null", key = "#uid")
    public List<String> queryPermissionByUserId(Long uid) {
        return baseDao.queryPermissionByUserId(uid);
    }

    @Override
    @Cacheable(cacheNames = CACHE_NAME, condition = "#roleId!=null", key = "#roleId")
    public List<String> queryPermissionByRoleId(Long roleId) {
        return baseDao.queryPermissionByRoleId(roleId);
    }

    @Override
    public SysResource findByUrlAndRequestMethod(String url, String requestMethod) {
        return baseDao.findByUrlAndRequestMethod(url, requestMethod);
    }

    @Override
    public SysResource findByNameAndType(String name, EResourceType type) {
        return baseDao.findByNameAndType(name, type);
    }
}
